package com.test.resource;

import java.io.InputStream;

/**
 * 实现了Resource接口的类路径资源类
 * 用于加载类路径下的资源文件
 */
public class ClassPathResource implements Resource{

    // 资源路径
    private final String path;
    // 类加载器
    private final ClassLoader classLoader;

    /**
     * 单参数构造函数
     * 使用默认的类加载器
     * @param path 资源路径，不能为空
     */
    public ClassPathResource(String path) {
        this(path, null);
    }

    /**
     * 双参数构造函数
     * @param path 资源路径，不能为空
     * @param classLoader 类加载器，如果为null则使用默认的类加载器
     */
    public ClassPathResource(String path, ClassLoader classLoader) {
        if (path == null){
            throw new IllegalArgumentException("路径不能为空");
        }
        this.path = path.startsWith("/") ? path.substring(1) : path;
        this.classLoader = (classLoader != null ? classLoader : getDefaultClassLoader());
    }

    /**
     * 获取默认的类加载器
     * 首先尝试获取线程上下文类加载器，如果获取不到则尝试获取当前类加载器，
     * 如果还获取不到则尝试获取系统类加载器
     * @return 默认的类加载器，可能为null
     */
    private static ClassLoader getDefaultClassLoader() {
        ClassLoader cl = null;
        try {
            cl = Thread.currentThread().getContextClassLoader();
        } catch (Throwable ex) {
            //无法获取线程上下文类加载器时忽略
        }
        if (cl == null) {
            cl = ClassPathResource.class.getClassLoader();
            if (cl == null) {
                try {
                    cl = ClassLoader.getSystemClassLoader();
                } catch (Throwable ex) {
                    //无法获取系统类加载器时忽略
                }
            }
        }
        return cl;
    }


    /**
     * 判断资源是否存在
     * @return 如果资源存在返回true，否则返回false
     */
    @Override
    public boolean exists() {
        return classLoader.getResource(path) != null;
    }

    /**
     * 判断资源是否可读
     * 类路径资源始终可读
     * @return 始终返回true
     */
    @Override
    public boolean isReadable() {
        return true;
    }

    /**
     * 获取资源的输入流
     * @return 资源的输入流
     * @throws Exception 如果资源不存在则抛出异常
     */
    @Override
    public InputStream getInputStream() throws Exception {
        InputStream is = classLoader.getResourceAsStream(path);
        if (is == null) {
            throw new Exception("类路径资源 [" + path + "] 不存在");
        }
        return is;
    }

    /**
     * 获取资源的描述信息
     * @return 资源的描述信息
     */
    @Override
    public String getDescription() {
        return "类路径资源 [" + path + "]";
    }

    /**
     * 获取类加载器
     * @return 类加载器，可能为null
     */
    public ClassLoader getClassLoader() {
        return classLoader;
    }

    /**
     * 获取资源路径
     * @return 资源路径
     */
    public String getPath() {
        return path;
    }
}
